#include <kernel.h>
#include <pa4.h>
//#include <disk.h>

/*
 * Part A 4/4. buf_put()
 * buf_put() processes each write request.
 * If policy is POLICY_WRITE_THROUGH,
 *     then find a buffer that already stores the block_no block, stores new data to it
 *     and finally store the data into disk.
 * Otherwise (POLICY_DELAYED_WRITE),
 *     then you have to handle requests based on the policy.
*/

dsk_buffer_p buf_search1(int block_no,int pdev)
{

dsk_buffer_p temp;

temp = buf_head;
        while(temp != NULL)
        {
                if( (temp->block_no == block_no) && (temp->pdev==pdev))
                {
                        return temp;

                }
                temp=temp->next;
        }
        return temp;
}






int buf_put(struct devsw *pdev, int block_no, char *buffer, int policy)
{
//STATWORD ps;
dsk_buffer_p buf_blk,temp,tmp;
int repl_pol;

repl_pol = PA4_BUFFER_REPLACEMENT;

//disable(ps);  // is this needed

/*      if( (block_no < 0) || (block_no > PA4_BUFFER_SIZE))
        {
                //restore(ps);
                return INVALID_BLOCK;
        }
*/

kprintf("Buf put called\n");

  if(pdev==&devtab[DISK0])
  {
        while(invalid[block_no] == 1)
        {
        kprintf("Another process has already requested for block no %d hence suspending this process till the block is fetched\n",block_no);

        resched();
        }

  }
  else
  {
        while(invalid2[block_no] == 1)
        {
        kprintf("Another process has already requested for block no %d hence suspending this process till the block is fetched\n",block_no);

        resched();
        }


  }



//      invalid[block_no] = 1;


        buf_blk = buf_search1(block_no,pdev);

        //kprintf("buf_blk = %d\n",buf_blk->block_no);

        if(buf_blk!=NULL)//present in buffer
        {
                buf_blk->data=buffer;
                kprintf("block found : %d\n",buf_blk->block_no);
                if(policy == POLICY_WRITE_THROUGH)
                {
                 kprintf("Policy is write through\n");
                        if(pdev==&devtab[DISK0])
                        invalid[block_no]=1;
                        else
                        invalid2[block_no]=1;
                        dskwrite(pdev,buf_blk->data,block_no,1);
                        kprintf("written to disk\n");
                        if(pdev==&devtab[DISK0])
                        invalid[block_no]=0;
                        else
                        invalid2[block_no]=0;
                        return OK;
                }
                else
                {
                        buf_blk->dirty = 1;
                       /* if(pdev==&devtab[DISK0])
                        IsBlockRequested[block_no]=0;
                        else
                        IsBlockRequested2[block_no]=0;*/
                        return OK;
                }
        }




        else if(buf_blk == NULL)
        {
        //buf_blk = buf_fetch(pdev,block_no,repl_pol);
        //buf_blk->data = buffer;


/*      tmp = buf_head;
        temp = tmp->next;

                while(temp->next != NULL)
                {
                tmp=temp;
                temp=temp->next;
                }
                temp->block_no = block_no;
                temp->pdev=pdev;
                temp->size =128;
                temp->data = buffer;
                tmp->next = NULL;
                temp->next=buf_head->next;
                temp=buf_head;

        */
        kprintf("block not found\n");
                if(buf_head)
                eviction(1);
                if(!buf_head)
                buf_head=buf_blk;
                //printf("\n IN HERE ? ");
                buf_blk->block_no = block_no;
                buf_blk->pdev = pdev;
                buf_blk->size = 128;
                buf_blk->data = buffer;
                buf_blk->next = NULL;
                buf_count++;





                if(policy == POLICY_WRITE_THROUGH)
                {

                 if(pdev==&devtab[DISK0])
                  {
                        while(invalid[block_no] == 1)
                        {
                        }
                        invalid[block_no] = 1;
                        dskwrite(pdev,buffer,block_no,1);
                         kprintf("disk written!!!!!!!!!!!!!!!1\n");
                        invalid[block_no] = 0;
                  }
                        //invalid[block_no]=1;

                if(pdev==&devtab[DISK1])
                  {
                        while(invalid2[block_no] == 1)
                        {
                        }
                        invalid2[block_no] = 1;
                        dskwrite(pdev,buffer,block_no,1);
                        invalid[block_no] = 0;
                  }
                        //dskwrite(pdev,buf_blk->data,block_no,1);
                        //invalid[block_no]=0;
                        return OK;
                }
                else
                {
                buf_blk->dirty = 1;
                return OK;
                }


        }

}
